From c33dddd505604372cddcf3b5f260141fce6e7a2d Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 7 Jul 2016 23:11:22 -0700 Subject: [PATCH] Generate the same lock always in a workspace Previously the "root" of a lock file would erroneously change over time, so instead just ensure that the root of a lock file is always the root of the workspace. Otherwise the contents should always be the same. Closes #2837 --- src/cargo/core/resolver/encode.rs | 23 ++++++++++---- src/cargo/core/resolver/mod.rs | 6 ++-- src/cargo/ops/lockfile.rs | 6 +++- tests/workspaces.rs | 50 +++++++++++++++++++++++++++++++ 4 files changed, 75 insertions(+), 10 deletions(-) diff --git a/src/cargo/core/resolver/encode.rs b/src/cargo/core/resolver/encode.rs index fb786bc18..256e7a49c 100644 --- a/src/cargo/core/resolver/encode.rs +++ b/src/cargo/core/resolver/encode.rs @@ -200,21 +200,32 @@ impl Decodable for EncodablePackageId { } } -impl Encodable for Resolve { +pub struct WorkspaceResolve<'a, 'cfg: 'a> { + pub ws: &'a Workspace<'cfg>, + pub resolve: &'a Resolve, +} + +impl<'a, 'cfg> Encodable for WorkspaceResolve<'a, 'cfg> { fn encode(&self, s: &mut S) -> Result<(), S::Error> { - let mut ids: Vec<&PackageId> = self.graph.iter().collect(); + let mut ids: Vec<&PackageId> = self.resolve.graph.iter().collect(); ids.sort(); + let root = self.ws.members().max_by_key(|member| { + member.name() + }).unwrap().package_id(); + let encodable = ids.iter().filter_map(|&id| { - if self.root == *id { return None; } + if root == id { + return None + } - Some(encodable_resolve_node(id, self)) + Some(encodable_resolve_node(id, self.resolve)) }).collect::>(); EncodableResolve { package: Some(encodable), - root: encodable_resolve_node(&self.root, self), - metadata: self.metadata.clone(), + root: encodable_resolve_node(&root, self.resolve), + metadata: self.resolve.metadata.clone(), }.encode(s) } } diff --git a/src/cargo/core/resolver/mod.rs b/src/cargo/core/resolver/mod.rs index 6d992a067..58cf94e0a 100644 --- a/src/cargo/core/resolver/mod.rs +++ b/src/cargo/core/resolver/mod.rs @@ -61,7 +61,7 @@ use util::ChainError; use util::graph::{Nodes, Edges}; pub use self::encode::{EncodableResolve, EncodableDependency, EncodablePackageId}; -pub use self::encode::Metadata; +pub use self::encode::{Metadata, WorkspaceResolve}; mod encode; @@ -674,7 +674,7 @@ fn build_features(s: &Summary, method: &Method) match s.features().get(feat) { Some(wanted_features) => { for entry in wanted_features { - // If the entry is of the form `foo/bar`, then we just lookup package + // If the entry is of the form `foo/bar`, then we just lookup package // `foo` and enable its feature `bar`. We also add `foo` to the used // set because `foo` might have been an optional dependency. // @@ -703,7 +703,7 @@ fn build_features(s: &Summary, method: &Method) deps.entry(feat.to_string()).or_insert(Vec::new()); } } - + visited.remove(&feat.to_string()); Ok(()) diff --git a/src/cargo/ops/lockfile.rs b/src/cargo/ops/lockfile.rs index 1c3a1f108..f0a1f72c3 100644 --- a/src/cargo/ops/lockfile.rs +++ b/src/cargo/ops/lockfile.rs @@ -4,6 +4,7 @@ use rustc_serialize::{Encodable, Decodable}; use toml::{self, Encoder, Value}; use core::{Resolve, resolver, Workspace}; +use core::resolver::WorkspaceResolve; use util::{CargoResult, ChainError, human, Filesystem}; use util::toml as cargo_toml; @@ -33,7 +34,10 @@ pub fn load_pkg_lockfile(ws: &Workspace) -> CargoResult> { pub fn write_pkg_lockfile(ws: &Workspace, resolve: &Resolve) -> CargoResult<()> { let mut e = Encoder::new(); - resolve.encode(&mut e).unwrap(); + WorkspaceResolve { + ws: ws, + resolve: resolve, + }.encode(&mut e).unwrap(); let mut out = String::new(); diff --git a/tests/workspaces.rs b/tests/workspaces.rs index c25809cbb..3e980547a 100644 --- a/tests/workspaces.rs +++ b/tests/workspaces.rs @@ -1,6 +1,10 @@ +#[macro_use] extern crate cargotest; extern crate hamcrest; +use std::io::Read; +use std::fs::File; + use cargotest::support::{project, execs}; use cargotest::support::registry::Package; use hamcrest::{assert_that, existing_file, existing_dir, is_not}; @@ -774,3 +778,49 @@ this may be fixable by ensuring that this crate is depended on by the workspace root: [..] ")); } + +#[test] +fn lock_doesnt_change_depending_on_crate() { + let p = project("foo") + .file("Cargo.toml", r#" + [project] + name = "foo" + version = "0.1.0" + authors = [] + + [workspace] + members = ['baz'] + + [dependencies] + foo = "*" + "#) + .file("src/lib.rs", "") + .file("baz/Cargo.toml", r#" + [project] + name = "baz" + version = "0.1.0" + authors = [] + + [dependencies] + bar = "*" + "#) + .file("baz/src/lib.rs", ""); + p.build(); + + Package::new("foo", "1.0.0").publish(); + Package::new("bar", "1.0.0").publish(); + + assert_that(p.cargo("build"), + execs().with_status(0)); + + let mut lockfile = String::new(); + t!(t!(File::open(p.root().join("Cargo.lock"))).read_to_string(&mut lockfile)); + + assert_that(p.cargo("build").cwd(p.root().join("baz")), + execs().with_status(0)); + + let mut lockfile2 = String::new(); + t!(t!(File::open(p.root().join("Cargo.lock"))).read_to_string(&mut lockfile2)); + + assert_eq!(lockfile, lockfile2); +} -- 2.30.2